Material design Animations

Material design Animations

[TOC]

定制窗口转换动画

首先,在定义您从材料主题继承的风格时,使用 android:windowContentTransitions 属性启用窗口内容转换。您也可在您的风格定义中指定进入、退出以及共享元素转换,可以在 application theme 中或 activity theme 中设置,如:

1
2
3
4
5
6
7
8
9
<style name="MaterialAnimations" parent="@style/Theme.AppCompat.Light.NoActionBar">
<item name="android:statusBarColor">@color/material_animations_primary_dark</item>
<item name="android:windowContentTransitions">true</item> //启用窗口内容转换
<item name="android:windowAllowEnterTransitionOverlap">false</item> //新窗口B入场动画是否要与当前窗口A的退出动画同时发生
<item name="android:windowAllowReturnTransitionOverlap">false</item> //与上面类似,重新进入A的入场与B的退出动画是否要一起发生
<item name="android:titleTextAppearance">@style/MaterialAnimations.TextAppearance.Title
</item>
<item name="android:windowBackground">@color/light_grey</item>
</style>

如果要尽快开始进入转换,请针对被调用的操作行为使用 Window.setAllowEnterTransitionOverlap() 方法。这可以让您实现更生动的进入转换。

具体的窗口转场动画可以在 代码中定义也可以在 XML 中定义。

过渡(Transition)动画类型

进入退出动画效果

默认提供了三种过渡动画类型:

  1. Slide—–滑 动:从场景边缘移入或移出视图
  2. Fade—–淡入淡出:通过调整透明度在场景中增添或移除视图
  3. Explode—–分 解:从场景中心移入或移出视图

共享元素

  1. changeBounds - 为目标视图的布局边界的变化添加动画。
  2. changeClipBounds - 为目标视图的裁剪边界的变化添加动画。
  3. changeTransform - 为目标视图的缩放与旋转变化添加动画。
  4. changeImageTransform - 为目标图像的大小与缩放变化添加动画。

Circlr Reveal

由代码指定转场动画

1
2
3
4
5
6
7
8
9
10
private void setupWindowAnimations() {
Slide slideTransition = new Slide();
slideTransition.setSlideEdge(Gravity.LEFT); // left top right bottom start end
slideTransition.setDuration(500);
getWindow().setReenterTransition(slideTransition); // 回到这个窗口时执行动画 内容区的 View 从左侧滑入
getWindow().setExitTransition(slideTransition); //退出动画 内容区的 View 从左侧滑出
//还可以设置
//getWindow().setEnterTransition(enterTransition);
//enterTransition.excludeTarget(int targetId, boolean exclude); // 排除一些不参加动画的View
}

Fade、Explode 动画设置方式与上面类似。当我们设置了转场动画后,Activity的启动方式需要使用

1
startActivity(Intent intent, @Nullable Bundle options)

这个方法,第二个参数 options(一些额外的选项关于怎样启动新 Activity) 我们需要传入一个 ActivityOptionsCompat 对象然后用 toBundle() 转换成 Bundle 对象。ActivityOptionsCompat 对象可以通过下面的方法创建:

1
2
3
4
5
// pairs 中可以添加系统 UI ,如 statusBarBackground、navigationBarBackground, 添加后这些组件将会参与过渡动画中
static ActivityOptionsmakeSceneTransitionAnimation(Activity activity, Pair...<View, String> sharedElements)
// 共享元素
static ActivityOptions makeSceneTransitionAnimation(Activity activity, View sharedElement, String sharedElementName)

可以新建一个辅助类提供一下方法来创建 pairs:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
public static Pair<View, String>[] createSafeTransitionParticipants(@NonNull Activity activity,
boolean includeStatusBar, @Nullable Pair... otherParticipants) {
// Avoid system UI glitches as described here:
// https://plus.google.com/+AlexLockwood/posts/RPtwZ5nNebb
View decor = activity.getWindow().getDecorView();
View statusBar = null;
if (includeStatusBar) {
statusBar = decor.findViewById(android.R.id.statusBarBackground);
}
View navBar = decor.findViewById(android.R.id.navigationBarBackground);
// Create pair of transition participants.
List<Pair> participants = new ArrayList<>(3);
addNonNullViewToTransitionParticipants(statusBar, participants);
addNonNullViewToTransitionParticipants(navBar, participants);
// only add transition participants if there's at least one none-null element
if (otherParticipants != null && !(otherParticipants.length == 1
&& otherParticipants[0] == null)) {
participants.addAll(Arrays.asList(otherParticipants));
}
return participants.toArray(new Pair[participants.size()]);
}
private static void addNonNullViewToTransitionParticipants(View view, List<Pair> participants) {
if (view == null) {
return;
}
participants.add(new Pair<>(view, view.getTransitionName()));
}

由 XML 指定转场动画

代码中加载动画:

1
2
Transition transition = TransitionInflater.from(this).inflateTransition(R.transition.explode);
getWindow().setEnterTransition(transition);

XML文件:

1
2
3
4
5
6
<?xml version="1.0" encoding="utf-8"?>
<transitionSet xmlns:android="http://schemas.android.com/apk/res/android">
<explode
android:duration="@integer/anim_duration_long"
android:interpolator="@android:interpolator/bounce" />
</transitionSet>

默认退出动画

如果我们没有设置 setReturnTransition ,finishAfterTransition(),这个方法会在 Activity 退出时反转入场动画 EnterTransition,并在动画结束后 finish() 这个Activity。如果设置了 setReturnTransition ,finishAfterTransition() 的退出动画就会反转 ReturnTransition。 没有设置入场动画的画,会直接调用 finish()。

共享元素动画

  1. ChangeBounds -捕获共享元素的layout bound,然后播放layout bound变化动画。ChangeBounds 是共享元素变换中用的最多的,因为前后两个activity中共享元素的大小和位置一般都是不同的。

  2. ChangeTransform - 捕获共享元素的缩放(scale)与旋转(rotation)属性 ,然后播放缩放(scale)与旋转(rotation)属性变化动画。

  3. ChangeClipBounds - 捕获共享元素clip bounds,然后播放clip bounds变化动画。

  4. ChangeImageTransform - 捕获共享元素(ImageView)的transform matrices 属性,然后播放ImageViewtransform matrices 属性变化动画。与ChangeBounds相结合,这个变换可以让ImageView在动画中高效实现大小,形状或者ImageView.ScaleType 属性平滑过度。

@android:transition/move - 将上述所有变换同时进行的一个TransitionSet 。就如在第一章中所讲的一样,如果共享元素的进入和返回变换没有特别声明,框架将使用它作为默认的变换。

共享的元素需要在 XML 里面制定 android:transitionName 值一样,Fragment 和 Activity 中的调用方法也不一样。Activity 里面可以将共享元素添加到 pair 键值对中,来启动。而 Fragment 则利用类似的方法:

1
2
3
sharedElementFragment.setReenterTransition(slideTransition);
sharedElementFragment.setExitTransition(slideTransition);
sharedElementFragment.setSharedElementEnterTransition(new ChangeBounds());

参考